package de.koller.worlders.gameplay.ability;

import de.koller.oceanFramework.glyph.GlyphRendererGL;
import de.koller.oceanFramework.math.Vec;
import de.koller.oceanFramework.util.Stat;
import de.koller.worlders.engine.entity.IAABB;
import de.koller.worlders.engine.entity.deco.Deco;
import de.koller.worlders.engine.entity.deco.Gem;
import de.koller.worlders.engine.entity.deco.Torch;
import de.koller.worlders.engine.entity.plattform.IPlattformEffect;
import de.koller.worlders.engine.entity.plattform.Plattform;
import de.koller.worlders.engine.entity.plattform.SolidPlattform;
import de.koller.worlders.engine.tiles.Tile;
import de.koller.worlders.gameplay.gui.MouseHold;
import de.koller.worlders.gameplay.items.BlueGemI;
import de.koller.worlders.gameplay.items.Item;
import de.koller.worlders.gameplay.items.WhiteStoneI;
import java.util.ArrayList;
import java.util.List;

public class MineAbility extends Ability {

	public static final int MINE_FREQUENZ = 500;
	private long nextMineable = 0;
	private final Stat mineDistance = new Stat();
	private boolean aval = false;
	
	public MineAbility() {
		mineDistance.getValues().put( "default", 1.8d );
	}
	
	@Override
	public void activeUpdate() {
		super.activeUpdate();
		
		MouseHold m = wroot.getGui().mouse;
		GlyphRendererGL g = m.getVisual().getRenderer();
		
		Vec v = wroot.getEntityContainer().getMouseWorldPosition();
		updateAval( v.getXi(), v.getYi() );
		m.setWorldPos( v.getXi(), v.getYi() );
		
		g.setCurrentBackColor( 0x00000000 );
		g.setCurrentFontColor( aval ? 0xff17630e : 0xffff0000 );
		if( wroot.getTime() < nextMineable )
			g.setCurrentFontColor( 0xffffff00 );
		
		g.renderGlyph( 0, 0, 6, 9 );
		g.renderGlyph( 1, 0, 7, 9 );
		g.renderGlyph( 2, 0, 8, 9 );

		g.renderGlyph( 0, 1, 6, 10 );
		g.renderGlyph( 1, 1, 7, 10 );
		g.renderGlyph( 2, 1, 8, 10 );
		
		float s = ((float)MouseHold.TEX_SIZE+1f) / 24f;
		m.setScale( s, s );
		
		if( wroot.getTime() < nextMineable )
			return;
		
		if( aval && wroot.getInput().isMouseDown( 1 ) )
			build( v.getXi(), v.getYi() );
		if( aval && wroot.getInput().isMouseDown( 0 ) )
			mine( v.getXi(), v.getYi() );
		if( aval && wroot.getInput().isMousePressed( 2 ) )
			torch( v.getXi(), v.getYi() );
	}
	
	private void torch( int tx, int ty ) {
		Tile t = wroot.getTileMap().getTileAt( tx+0.5f, ty+0.5f ).getTile();
		if( t.getTileEntity() != null )
			return;
			
		if( t.getDeco() instanceof Torch )
			wroot.getTileMap().tileHolder.changeMapData( tx, ty, -1, -1, 0xff, -1 );
		else if( t.getDeco() == null )
			wroot.getTileMap().tileHolder.changeMapData( tx, ty, -1, -1, Torch.GEN_ID, -1 );
		wroot.getTileMap().reloadTile( tx, ty );
		nextMineable = wroot.getTime() + MINE_FREQUENZ;
	}
	
	private void build( int tx, int ty ) {
		Tile t = wroot.getTileMap().getTileAt( tx+0.5f, ty+0.5f ).getTile();
		if( t.getTileEntity() != null )
			return;
		
		if( !wroot.inventory.removeItem( WhiteStoneI.class, 1 ) ) return;
		
		wroot.getTileMap().tileHolder.changeMapData( tx, ty, SolidPlattform.GEN_ID, 4, 0, -1 );
		wroot.getTileMap().reloadTile( tx, ty );
		nextMineable = wroot.getTime() + MINE_FREQUENZ;
	}
	
	private void updateAval( int tx, int ty ) {
		IAABB p = wroot.gamePlayer.getGPO().getAABB();
		float cx = p.getPosition().getXf() + p.getSize().getXf()*0.5f;
		float cy = p.getPosition().getYf() + p.getSize().getYf()*0.5f;
		Vec c = new Vec( cx, cy );
		
		float dx = Math.abs( (tx+.5f) - c.getXf() );
		float dy = Math.abs( (ty+.5f) - c.getYf() );

		if( dx > mineDistance.valueF() ) aval = false;
		else if( dy > mineDistance.valueF() ) aval = false;
		else aval = true;
	}
	
	private void mine( int tx, int ty ) {
		Tile t = wroot.getTileMap().getTileAt( tx+0.5f, ty+0.5f ).getTile();
		if( !isMineableTile( t ) )
			return;

		List< Class<? extends Item> > drops = droppedItems( t );
		for( Class<? extends Item> i : drops )
			wroot.inventory.addItem( i, 1 );
		
		wroot.getTileMap().tileHolder.changeMapData( tx, ty, 0xff, 0xff, 0xff, -1 );
		wroot.getTileMap().reloadTile( tx, ty );
		nextMineable = wroot.getTime() + MINE_FREQUENZ;
	}
	
	private boolean isMineableTile( Tile t ) {	
		return isWhiteStone( t );
	}
	
	private List< Class<? extends Item> > droppedItems( Tile t ) {
		List< Class<? extends Item> > l = new ArrayList<>();
		
		if( Deco.contains( t, Gem.class ) ) l.add( BlueGemI.class );
		else if( isWhiteStone( t ) ) l.add( WhiteStoneI.class );
		return l;
	}
	
	private boolean isWhiteStone( Tile t ) {
		if( t.getTileEntity() instanceof Plattform == false )
			return false;
		
		Plattform p = (Plattform)t.getTileEntity();
		for( IPlattformEffect e : p.getEffects() )
			if( e instanceof SolidPlattform && ((SolidPlattform)e).getType() == SolidPlattform.SolidType.White )
				return true;
		return false;
	}
}
